/**
 * @author
 * Aldebaran Robotics (c) 2007 All Rights Reserved - This is an example of use.\n
 *
 */

#ifndef GVMsample_H
#define GVMsample_H
#include "genericvideomodule.h"
#include "alloggerproxy.h"
#include "almemoryproxy.h"
#include "alptr.h"
#include <string>
#include "opencv/highgui.h"

using namespace std;

namespace AL 
{

/**
 * This class shows how to use the Video Input Module to register images.
 * It internally uses OpenCv's cvSaveImage function.
 */
class GVMsample : public AL::ALModule
{

  public:
    
    /**
     * Default Constructor.
     */
    GVMsample( ALPtr<ALBroker> pBroker, const std::string& pName );

    /**
     * Destructor.
     */
     virtual ~GVMsample();
     
    /**
     * registerToVIM : Register to the V.I.M.
     */
    void registerToVIM(const int &pResolution, const int &pColorSpace, const int &pFps);
    
    /**
     * unRegisterFromVIM : Unregister from the V.I.M.
     */
    void unRegisterFromVIM();

    /**
     * saveImage : save the last image received.
     * @param pName name of the file
     */
    void saveImageLocal(const std::string& pName, const std::string& imageFormat);

    /**
     * saveImageRemote : save the last image received. To be used if genericvideomodule is a remote module.
     * @param pName name of the file
     */
    void saveImageRemote(const std::string& pName, const std::string& imageFormat);

    /**
     * startGrabbing: creates a worker thread that grabs an image and dumps it into ALMemory at the
     * specified framerate.
     */

    void startGrabbing();

    /**
     * stopGrabbing: Kills the worker thread and stops the grabbing.
     */

    void stopGrabbing();


    /**
     * version
     * @return The version number of ALLeds
     */
    std::string version();

    /**
     * grabFrames: Called in a worker thread to do the actual grabbing loop
     */
    void grabFrames();

    /**
     * innerTest
     * @return True if all the tests passed
     */
    bool innerTest(){ return true;};

    // Automatically called right after the module is created.
    virtual void init();

    static const std::string frameMemoryAddress;
  
  private:

    // Actually perform the cvSaveImage operation.
    void saveIplImage(const IplImage* img, const std::string& name,
                      const std::string& format, int seconds);

    // Proxy to the logger module.
    ALPtr<AL::ALLoggerProxy> fLogProxy;

    // Proxy to the video input module.
    ALPtr<AL::ALProxy> fCamProxy;

    //Proxy to the memory module where we keep the result
    ALPtr<AL::ALProxy> fMemoryProxy;

    //Proxy to the module itself (need it to make nice parallel calls.
    ALPtr<AL::ALProxy> fThisProxy;

    //Needed to track parallel calls
    ALPtr<AL::ALTaskMonitor> fTaskMonitor;

    //GVM parameters
    string fGvmName;
    int fFPS;
  
    //used for tracking parallel calls
    int fGrabberID;

    // This is set to true when we have subscribed one module to the VideoDevice.
    bool fRegisteredToVim;

    // Just a IplImage header to wrap around our camera image buffer.
    // This object doesn't own the image buffer.
    IplImage* fIplImageHeader;

    pthread_mutex_t fGrabberMutex;
};


} // namespace AL

#endif // GVMsample_H
